﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XNAGuiLib.GuiLibResourceManager;
using Microsoft.Xna.Framework.Content;
using System.Globalization;

namespace XNAGuiLib.GuiLibFrames
{
    public class FrameObject : InterfaceObject
    {
        protected int sepCnt = 1;
        public GuiResourceManager.ResourceManagerType ResourceType;

        #region Enumeration - SeperatorAlign
        public enum SeperatorAlign
        {
            Horizontal,
            Vertical
        }
        #endregion


        #region Field - TitleFont
        private SpriteFont _titleFont;
        /// <summary>
        /// gets or sets the titlefont of the Frame
        /// </summary>
        public SpriteFont TitleFont
        {
            get
            {
                return _titleFont;
            }
            set
            {
                _titleFont = value;
            }
        }
        #endregion

        #region Field - Corner
        protected Texture2D _corner;
        /// <summary>
        /// gets or sets the Corner Texture2D
        /// </summary>
        public Texture2D Corner
        {
            get
            {
                return _corner;
            }
            set
            {
                _corner = value;
            }
        }
        #endregion

        #region Field - Side
        protected Texture2D _side;
        /// <summary>
        /// gets or sets the Side Texture2D
        /// </summary>
        public Texture2D Side
        {
            get
            {
                return _side;
            }
            set
            {
                _side = value;
            }
        }
        #endregion

        #region Field - Background
        protected Texture2D _background;
        /// <summary>
        /// gets or sets the Background Texture2D
        /// </summary>
        public Texture2D Background
        {
            get
            {
                return _background;
            }
            set
            {
                _background = value;
            }
        }
        #endregion

        #region Field - Scale
        /// <summary>
        /// gets or sets the InterfaceObjects scale
        /// </summary>
        public new Vector2 Scale
        {
            get
            {
                return _scale;
            }
            set
            {
                _scale = value;

                BackgroundDefault.Scale = value;
            }
        }
        #endregion

        #region Field - Background
        /// <summary>
        /// gets or sets BackgroundDefault
        /// </summary>
        public TextureObject BackgroundDefault { get; set; }
        #endregion

        #region Fields - Corners
        /// <summary>
        /// gets or sets CornerUpperLeft
        /// </summary>
        public TextureObject CornerUpperLeft { get; set; }
        /// <summary>
        /// gets or sets CornerUpperRight
        /// </summary>
        public TextureObject CornerUpperRight { get; set; }
        /// <summary>
        /// gets or sets CornerLowerLeft
        /// </summary>
        public TextureObject CornerLowerLeft { get; set; }
        /// <summary>
        /// gets or sets CornerLowerRight
        /// </summary>
        public TextureObject CornerLowerRight { get; set; }
        #endregion

        #region Fields - Sides
        /// <summary>
        /// gets or sets SideLeft
        /// </summary>
        public TextureObject SideLeft { get; set; }
        /// <summary>
        /// gets or sets SideRight
        /// </summary>
        public TextureObject SideRight { get; set; }
        /// <summary>
        /// gets or sets SideTop
        /// </summary>
        public TextureObject SideTop { get; set; }
        /// <summary>
        /// gets or sets SideBottom
        /// </summary>
        public TextureObject SideBottom { get; set; }
        #endregion


        #region Constructor - FrameObject(Game game, string name, string title, int x, int y, int width, int height, bool visible)
        public FrameObject(Game game, string name, string title, int x, int y, int width, int height, bool visible) 
            : base(game, name, new Vector2(x, y), visible)
        {
            Position = new Vector2(x, y);

            Width = width;
            Height = height;
            Title = title;

            _titleFont = GuiResourceManager.Instance(this.Game).FontManager.Load<SpriteFont>("DefaultFrame");
        }
        #endregion


        #region Method - AddText(TextObject textObject)
        /// <summary>
        /// adds a TextObject with its position relative to the upperleft corner of the FrameObject
        /// </summary>
        /// <param name="textObject">TextObject to add</param>
        public void AddText(TextObject textObject)
        {
            if (!textObject.Name.Equals("title")) textObject.RelativePosition += new Vector2(0, _titleFont.MeasureString(_title).Y);
            textObject.Position = _position;
            Add(textObject);
        }
        #endregion

        #region Method - AddImage(TextureObject textureObject)
        public void AddImage(TextureObject textureObject)
        {
            textureObject.Position = _position;
            Add(textureObject);
        }
        #endregion

        #region Method - UpdateText(string objectName, string updatedText)
        /// <summary>
        /// updates the TextObject in the List (if it exists) to the given updatedText
        /// </summary>
        /// <param name="objectName">name of the TextObject which should be updated</param>
        /// <param name="updatedText">new text</param>
        /// <param name="textColor">new textcolor</param>
        public void UpdateText(string objectName, string updatedText, Color textColor)
        {
            int index = SearchTextList(objectName);
            if (index >= 0)
            {
                _textObjs[index].Text = updatedText;
                _textObjs[index].TextColor = textColor;
            }
        }
        #endregion

        #region Method - UpdateImage(string objectName, Texture2D updatedTexture)
        /// <summary>
        /// updates the TextureObject in the List (if it exists) to the given updatedTexture
        /// </summary>
        /// <param name="objectName">name of the TextureObject which should be updated</param>
        /// <param name="updatedText">new texture</param>
        public void UpdateImage(string objectName, Texture2D updatedTexture)
        {
            int index = SearchTextureList(objectName);
            if (index >= 0)
            {
                _textureObjs[index].Texture = updatedTexture;
            }
        }
        #endregion

        /// <summary>
        /// cleans up the whole FrameObject (deletes all Objects from various lists!!)
        /// </summary>
        public void Clean()
        {
            _ios.Clear();
            _textObjs.Clear();
            _textureObjs.Clear();

            _initialized = false;
        }

        public void CreateCorners()
        {
            if (_corner != null)
            {
                // Positionen korrigieren
                CornerUpperLeft = new TextureObject(_corner, "_cu_left", new Vector2(0, 0), new Vector2(_corner.Width, _corner.Height));
                CornerUpperLeft.Rotation = MathHelper.ToRadians(0.0f);
                CornerUpperRight = new TextureObject(_corner, "_cu_right", new Vector2(20, 0), new Vector2(_corner.Width, _corner.Height));
                CornerUpperRight.Rotation = MathHelper.ToRadians(90.0f);
                CornerLowerRight = new TextureObject(_corner, "_cl_right", new Vector2(20, 20), new Vector2(_corner.Width, _corner.Height));
                CornerLowerRight.Rotation = MathHelper.ToRadians(180.0f);
                CornerLowerLeft = new TextureObject(_corner, "_cl_left", new Vector2(0, 20), new Vector2(_corner.Width, _corner.Height));
                CornerLowerLeft.Rotation = MathHelper.ToRadians(270.0f);
            }
        }

        public void CreateSides()
        {
            if (_side != null)
            {
                // Positionen / Bounds korrigieren
                SideTop = new TextureObject(_side, "_s_top", new Vector2(0, 0), new Vector2(_side.Width, _side.Height));
                SideRight = new TextureObject(_side, "_s_right", new Vector2(0, 0), new Vector2(_side.Width, _side.Height));
                SideBottom = new TextureObject(_side, "_s_bottom", new Vector2(0, 0), new Vector2(_side.Width, _side.Height));
                SideLeft = new TextureObject(_side, "_s_left", new Vector2(0, 0), new Vector2(_side.Width, _side.Height));
            }
        }

        public void CreateBackground()
        {
            if (_background != null)
            {
                // Positionen / Bounds korrigieren
                BackgroundDefault = new TextureObject(_side, "_bg", new Vector2(0, 0), new Vector2(_background.Width, _background.Height));
            }
        }



        #region Private Method - EndInitialize()
        public void EndInitialize()
        {
            if (!_initialized)
            {
                Add(BackgroundDefault);

                Add(CornerUpperLeft);
                Add(CornerUpperRight);
                Add(CornerLowerLeft);
                Add(CornerLowerRight);

                Add(SideTop);
                Add(SideRight);
                Add(SideBottom);
                Add(SideLeft);

                if (CornerUpperLeft != null)
                    AddText(new TextObject(_title, _titleFont, "title", new Vector2(CornerUpperLeft.Width + 1.0f, CornerUpperLeft.Height - 1.0f), Statics.ZeroVector2));
            }
        }
        #endregion

        #region Override Method - Update(GameTime gameTime)
        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            if (_corner != null && _background != null && _side != null)
                _initialized = true;
            else _initialized = false;

            if (this.IsInitialized)
            {
                base.Update(gameTime);
            }
        }
        #endregion

        #region Override Method - Rescale(Vector2 bounds)
        public override void Rescale(Vector2 bounds)
        {
            _bounds = bounds;
            if (_initialized)
            {
                // Rescale / Reposition CornerUpperLeft
                this.TextureObject(this._textureObjs.IndexOf(this.CornerUpperLeft)).Bounds = new Vector2(CornerUpperLeft.Width, CornerUpperLeft.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.CornerUpperLeft)).RelativePosition = new Vector2(0, 0);
                // Rescale / Reposition CornerUpperRight
                this.TextureObject(this._textureObjs.IndexOf(this.CornerUpperRight)).Bounds = new Vector2(CornerUpperRight.Width, CornerUpperRight.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.CornerUpperRight)).RelativePosition = new Vector2(bounds.X - Corner.Width, 0);
                // Rescale / Reposition CornerLowerLeft
                this.TextureObject(this._textureObjs.IndexOf(this.CornerLowerLeft)).Bounds = new Vector2(CornerLowerLeft.Width, CornerLowerLeft.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.CornerLowerLeft)).RelativePosition = new Vector2(0 + Corner.Width, bounds.Y);
                // Rescale / Reposition CornerLowerRight
                this.TextureObject(this._textureObjs.IndexOf(this.CornerLowerRight)).Bounds = new Vector2(CornerLowerRight.Width, CornerLowerRight.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.CornerLowerRight)).RelativePosition = new Vector2(bounds.X, bounds.Y);
                // Rescale / Reposition SideUp
                this.TextureObject(this._textureObjs.IndexOf(this.SideTop)).Bounds = new Vector2(bounds.X - (2 * Corner.Width), SideTop.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.SideTop)).RelativePosition = new Vector2(Corner.Width, 0);
                // Rescale / Reposition SideRight
                this.TextureObject(this._textureObjs.IndexOf(this.SideRight)).Bounds = new Vector2(bounds.Y - (2 * Corner.Width), SideRight.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.SideRight)).RelativePosition = new Vector2(bounds.X, Corner.Height);
                // Rescale / Reposition SideLow
                this.TextureObject(this._textureObjs.IndexOf(this.SideBottom)).Bounds = new Vector2(bounds.X - (2 * Corner.Width), SideBottom.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.SideBottom)).RelativePosition = new Vector2(bounds.X - Corner.Width, bounds.Y);
                // Rescale / Reposition SideLeft
                this.TextureObject(this._textureObjs.IndexOf(this.SideLeft)).Bounds = new Vector2(bounds.Y - (2 * Corner.Width), SideRight.Height);
                this.TextureObject(this._textureObjs.IndexOf(this.SideLeft)).RelativePosition = new Vector2(0, bounds.Y - Corner.Width);
                // Rescale / Reposition BackgroundDefault
                this.TextureObject(this._textureObjs.IndexOf(this.BackgroundDefault)).Bounds = new Vector2(bounds.X - (SideLeft.Height + SideRight.Height), bounds.Y - (SideTop.Height + SideBottom.Height));
                this.TextureObject(this._textureObjs.IndexOf(this.BackgroundDefault)).RelativePosition = new Vector2(SideLeft.Height, CornerUpperLeft.Height);
            }
        }
        #endregion

        #region Override Method - Draw(GameTime gameTime, SpriteBatch sprite)
        public override void Draw(GameTime gameTime, SpriteBatch sprite)
        {
            if (this.IsInitialized)
            {
                foreach (TextureObject textureObj in _textureObjs)
                {
                    textureObj.Draw(sprite);
                }

                foreach (TextObject textObj in _textObjs)
                {
                    textObj.Draw(sprite);
                }
            }
        }
        #endregion

    }
}